package org.example.rowing.service;

import javafx.scene.control.Label;
import lombok.extern.slf4j.Slf4j;
import org.example.rowing.domain.EventResult;
import org.example.rowing.domain.Race;
import org.example.rowing.domain.Registration;
import org.example.rowing.domain.Team;
import org.example.rowing.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RaceProcessCommonService {

    @Autowired
    private RegistrationInfoService registrationInfoService;
    @Autowired
    private RaceInfoService raceInfoService;
    @Autowired
    private ResultInfoService resultInfoService;

    public List<RegistrationVO> getRegistrationVOS(RaceVO raceVO) {
        if (raceVO == null || raceVO.getId() == null)
            return null;
        RegistrationVO registrationCondition = new RegistrationVO();
        registrationCondition.setRaceId(raceVO.getId());
        return registrationInfoService.showSearchedRegistrations(registrationCondition);
    }

    public List<RegistrationVO> getRegistrationVOByRaceId(Long raceId) {
        if (raceId == null)
            return null;
        RegistrationVO registrationCondition = new RegistrationVO();
        registrationCondition.setRaceId(raceId);
        return registrationInfoService.showSearchedRegistrations(registrationCondition);
    }

    public Integer sizeOfTeams(RaceVO raceVO) {
        if (raceVO == null || raceVO.getId() == null)
            return 0;
        RegistrationVO registrationCondition = new RegistrationVO();
        registrationCondition.setRaceId(raceVO.getId());
        List<RegistrationVO> registrationVOS = registrationInfoService.showSearchedRegistrations(registrationCondition);
        return registrationVOS.size();
    }

    public void SetFilling(Label label, RoundScoreVO roundScoreVO, Set<RoundScoreVO> p1Set, Set<RoundScoreVO> p2Set, Set<RoundScoreVO> sSet, Set<RoundScoreVO> f1Set, Set<RoundScoreVO> f2Set) {
        if (label.getId().startsWith("p1")) {
            p1Set.add(roundScoreVO);
        } else if (label.getId().startsWith("p2")) {
            p2Set.add(roundScoreVO);
        } else if (label.getId().startsWith("s")) {
            sSet.add(roundScoreVO);
        } else if (label.getId().startsWith("f1")) {
            f1Set.add(roundScoreVO);
        } else if (label.getId().startsWith("f2")) {
            f2Set.add(roundScoreVO);
        }
    }

    public void mapFilling(Label label, RoundScoreVO roundScoreVO, Map<String, Set<RoundScoreVO>> categoryMap) {
        for (String key : categoryMap.keySet()) {
            if (label.getId().startsWith(key)) {
                categoryMap.get(key).add(roundScoreVO);
                return;
            }
        }
    }

    public void saveFinalResult(List<RoundScoreVO> finalList, RaceVO raceVO) {
        Race race = raceInfoService.selectRaceById(finalList.get(0).getRaceId());
        if (race.getIsFinished()) {
            return;
        }

        log.info("被保存的榜单信息为：{}", finalList);
        for (int i = 0; i < finalList.size(); i++) {
            RoundScoreVO roundScoreVO = finalList.get(i);
            EventResult eventResultCondition = new EventResult(null, raceVO.getEventVO().getId(), roundScoreVO.getRegistrationVO().getTeam().getId(), null, null, null, null, null);
            List<EventResult> eventResults = resultInfoService.showSearchedEventResults(eventResultCondition);

            EventResult eventResult = null;
            if (!eventResults.isEmpty() && eventResults.get(0) != null) {
                eventResult = eventResults.get(0);
            } else {
                eventResult = new EventResult(null, raceVO.getEventVO().getId(), roundScoreVO.getRegistrationVO().getTeam().getId(), 0, 0, 0, 0, 0);
            }

            if (!roundScoreVO.getStatus().equals("NORMAL")) {
                continue;
            }

            if (i == 0) {
                eventResult.setGoldMedal(eventResult.getGoldMedal() + 1);
                eventResult.setTotalMedal(eventResult.getTotalMedal() + 1);
                eventResult.setTotalScore(eventResult.getTotalScore() + race.getFirstScore());
            } else if (i == 1) {
                eventResult.setSilverMedal(eventResult.getSilverMedal() + 1);
                eventResult.setTotalMedal(eventResult.getTotalMedal() + 1);
                eventResult.setTotalScore(eventResult.getTotalScore() + race.getSecondScore());
            } else if (i == 2) {
                eventResult.setBronzeMedal(eventResult.getBronzeMedal() + 1);
                eventResult.setTotalMedal(eventResult.getTotalMedal() + 1);
                eventResult.setTotalScore(eventResult.getTotalScore() + race.getThirdScore());
            } else if (i == 3) {
                eventResult.setTotalScore(eventResult.getTotalScore() + race.getForthScore());
            } else if (i == 4) {
                eventResult.setTotalScore(eventResult.getTotalScore() + race.getFifthScore());
            } else if (i == 5) {
                eventResult.setTotalScore(eventResult.getTotalScore() + race.getSixthScore());
            } else if (i == 6) {
                eventResult.setTotalScore(eventResult.getTotalScore() + race.getSeventhScore());
            } else if (i == 7) {
                eventResult.setTotalScore(eventResult.getTotalScore() + race.getEighthScore());
            }
            resultInfoService.saveOrUpdateEventResult(eventResult);
        }
        race.setIsFinished(true);
        raceInfoService.saveOrUpdateRace(race);
    }

    public List<RoundScoreVO> sortedEntries(List<RoundScoreVO> list) {
        list.sort((m1, m2) -> Double.compare(m1.getScore(), m2.getScore()));
        return list;
    }

    public List<RoundScoreVO> orderOptimization(List<RoundScoreVO> pRounds, List<RoundScoreVO> fRounds) {
        List<RoundScoreVO> listA = new ArrayList<>();
        List<RoundScoreVO> listB = new ArrayList<>();

        Map<String, RoundScoreVO> laneToTeamMap = new TreeMap<>();  // 按航道编号升序排列
        for (RoundScoreVO pRound : pRounds) {
            laneToTeamMap.put(pRound.getLane(), pRound);
        }
        for (Map.Entry<String, RoundScoreVO> entry : laneToTeamMap.entrySet()) {
            listA.add(entry.getValue());
        }

        if (fRounds.size() == 3) {
            listB.add(fRounds.get(2));
            listB.add(fRounds.get(0));
            listB.add(fRounds.get(1));
        } else if (fRounds.size() == 4) {
            listB.add(fRounds.get(2));
            listB.add(fRounds.get(0));
            listB.add(fRounds.get(1));
            listB.add(fRounds.get(3));
        } else if (fRounds.size() == 5) {
            listB.add(fRounds.get(4));
            listB.add(fRounds.get(2));
            listB.add(fRounds.get(0));
            listB.add(fRounds.get(1));
            listB.add(fRounds.get(3));
        } else if (fRounds.size() == 6) {
            listB.add(fRounds.get(4));
            listB.add(fRounds.get(2));
            listB.add(fRounds.get(0));
            listB.add(fRounds.get(1));
            listB.add(fRounds.get(3));
            listB.add(fRounds.get(5));
        }

        List<RoundScoreVO> list = processSwap(listA, listB);

        List<RoundScoreVO> result = new ArrayList<>();
        if (list.size() == 3) {
            result.add(list.get(1));
            result.add(list.get(2));
            result.add(list.get(0));
        } else if (list.size() == 4) {
            result.add(list.get(1));
            result.add(list.get(2));
            result.add(list.get(0));
            result.add(list.get(3));
        } else if (list.size() == 5) {
            result.add(list.get(2));
            result.add(list.get(3));
            result.add(list.get(1));
            result.add(list.get(4));
            result.add(list.get(0));
        } else if (list.size() == 6) {
            result.add(list.get(2));
            result.add(list.get(3));
            result.add(list.get(1));
            result.add(list.get(4));
            result.add(list.get(0));
            result.add(list.get(5));
        }

        return result;
    }

    public List<RoundScoreVO> processSwap(List<RoundScoreVO> A, List<RoundScoreVO> B) {
        // 生成A的所有长度>=3的连续子串的字符串表示（包括正序和逆序）
        Set<String> aSubSet = generateSubstrings(A);
        int n = B.size();
        boolean found = false;

        // 在B中查找是否存在与A相同的子串（长度>=3）
        for (int len = 3; len <= n; len++) {
            if (found) {
                break;
            }
            for (int start = 0; start <= n - len; start++) {
                // 获取B的子串（正序）
                List<RoundScoreVO> sub = B.subList(start, start + len);
                String forward = listToString(sub);

                // 检查正序是否匹配
                if (aSubSet.contains(forward)) {
                    found = true;
                    break;
                }

                // 检查逆序是否匹配
                String backward = listToStringReverse(sub);
                if (aSubSet.contains(backward)) {
                    found = true;
                    break;
                }
            }
        }

        // 如果找到匹配子串，根据B的长度执行交换
        if (found) {
            if (n == 3 || n == 4) {
                Collections.swap(B, 1, 2);
                log.info("应用优化：交换第1名和第2名队伍位置");
            } else if (n == 5 || n == 6) {
                Collections.swap(B, 1, 4);
                log.info("应用优化：交换第3名和第4名队伍位置");
            }
        }
        return B;
    }

    // 生成列表的所有连续子串（长度>=3）的字符串表示（只存储正序）
    private Set<String> generateSubstrings(List<RoundScoreVO> list) {
        Set<String> set = new HashSet<>();
        int n = list.size();
        for (int len = 3; len <= n; len++) {
            for (int start = 0; start <= n - len; start++) {
                List<RoundScoreVO> sub = list.subList(start, start + len);
                set.add(listToString(sub));
            }
        }
        return set;
    }

    // 将RoundScoreVO列表转换为逗号分隔的字符串（使用registrationId）
    private String listToString(List<RoundScoreVO> list) {
        return list.stream()
                .map(vo -> String.valueOf(vo.getRegistrationVO().getRegistrationId()))
                .collect(Collectors.joining(","));
    }

    // 将RoundScoreVO列表转换为逗号分隔的字符串（逆序）
    private String listToStringReverse(List<RoundScoreVO> list) {
        List<RoundScoreVO> reversed = new ArrayList<>(list);
        Collections.reverse(reversed);
        return listToString(reversed);
    }
}
